//
//  Transform.cpp
//  RenderV1
//
//  Created by 黄翔 on 2019/10/20.
//  Copyright © 2019 黄翔. All rights reserved.
//

#include "Transform.h"

hxe::Transform::Transform(GameObject* gameObject)
{
    position = Vector3(0.0f, 0.0f, 0.0f);
    scale = Vector3(1.0f, 1.0f, 1.0f);

    forward = Vector3(0.0f, 0.0f, 1.0f);
    up = Vector3(0.0f, 1.0f, 0.0f);
    right = Vector3(1.0f, 0.0f, 0.0f);

    this->gameObject = gameObject;
    this->parent = nullptr;
}


hxe::Transform::~Transform()
{
}

void hxe::Transform::setEulerAngles(const Vector3& eulerAngles)
{
    Matrix4x4 m = Matrix4x4(1.0f);
    m = glm::rotate(m, glm::radians(eulerAngles.x), Vector3(1.0f, 0.0f, 0.0f));
    m = glm::rotate(m, glm::radians(eulerAngles.y), Vector3(0.0f, 1.0f, 0.0f));
    m = glm::rotate(m, glm::radians(eulerAngles.z), Vector3(0.0f, 0.0f, 1.0f));
    
    right = glm::normalize(m[0]);
    up = glm::normalize(m[1]);
    forward = glm::normalize(m[2]);
}

Matrix4x4 hxe::Transform::getMatrix() const
{
    Matrix4x4 rotationMat;
    rotationMat[0] = Vector4(right, 0.0f);
    rotationMat[1] = Vector4(up, 0.0f);
    rotationMat[2] = Vector4(forward, 0.0f);
    rotationMat[3] = Vector4(0.0f, 0.0f, 0.0f, 1.0f);

    Matrix4x4 mat = Matrix4x4(1.0f);
    mat = glm::translate(mat, position);
    mat = glm::scale(mat, scale);
    mat = mat * rotationMat;

    if (this->parent != nullptr)
    {
        mat = this->parent->getMatrix() * mat;
    }
    return mat;
}

void hxe::Transform::setParent(Transform* parent)
{
    if (this->parent == parent)
    {
        return;
    }

    removeFromParent();

    this->parent = parent;
    if (this->parent != nullptr)
    {
        this->parent->children.push_back(this);
    }
}


void hxe::Transform::removeFromParent()
{
    if (this->parent == nullptr)
    {
        return;
    }

    for (unsigned int i = 0; i < this->parent->children.size(); i++)
    {
        if (this->parent->children[i] == this)
        {
            this->parent->children.erase(this->parent->children.begin() + i);
            break;
        }
    }
    this->parent = nullptr;
}

hxe::Transform* hxe::Transform::getParent() const
{
    return parent;
}


int hxe::Transform::getChildCount() const
{
    return children.size();
}

hxe::Transform* hxe::Transform::find(std::string name)
{
    for (unsigned int i = 0; i < children.size(); i++)
    {
        Transform* c = children[i];
        if (c->gameObject->name == name)
        {
            return c;
        }
    }
    return nullptr;
}

hxe::Transform* hxe::Transform::getChild(unsigned int index)
{
    if (index >= children.size())
    {
        return nullptr;
    }

    return children[index];
}
